package com.ying.config;

import com.ying.shiro.AuthConstant;
import com.ying.shiro.UserRealm;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;

import java.util.HashMap;
import java.util.Map;

/**
 * shiro 配置
 *
 * @author ziyan
 * @email 434595824@qq.com
 * @date 2017/10/16
 */
//@Configurable
public class ShiroConfiguration {

    @Bean
    public ShiroFilterFactoryBean shiroFilter() {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(new UserRealm());
        shiroFilter.setSecurityManager(securityManager);
        //要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.html"页面
        shiroFilter.setLoginUrl("/login.html");
        //登录成功后要跳转的连接
        shiroFilter.setSuccessUrl("/index.html");
        //用户访问未对其授权的资源时,所显示的连接
        shiroFilter.setUnauthorizedUrl("/");
        //Shiro连接约束配置,即过滤链的定义
        //anon：它对应的过滤器里面是空的,什么都没做
        //authc：该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
        Map<String, String> filterChainDefinitionMap = getFilterChainDefinitionMap();
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilter;
    }

    /**
     * 权限链
     *
     * @return
     */
    public Map<String, String> getFilterChainDefinitionMap() {
        Map<String, String> filterChainDefinitionMap = new HashMap<>();
        filterChainDefinitionMap.put("/statics/**", AuthConstant.ANON);
        filterChainDefinitionMap.put("/login.html", AuthConstant.ANON);
        filterChainDefinitionMap.put("/swagger-ui.html", AuthConstant.ANON);
        filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", AuthConstant.ANON);
        filterChainDefinitionMap.put("/images/**", AuthConstant.ANON);
        filterChainDefinitionMap.put("/error/**", AuthConstant.ANON);
        filterChainDefinitionMap.put("/comm/**", AuthConstant.ANON);
        filterChainDefinitionMap.put("/about/**", AuthConstant.ANON);
        filterChainDefinitionMap.put("/captcha.jpg", AuthConstant.ANON);
        filterChainDefinitionMap.put("/**", AuthConstant.AUTHC);
        return filterChainDefinitionMap;
    }

    //配置核心安全事务管理器
    @Bean
    public SecurityManager securityManager(@Qualifier("authRealm") UserRealm authRealm) {
        System.err.println("--------------shiro已经加载----------------");
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(authRealm);
        return manager;
    }

    //配置自定义的权限登录器
    @Bean
    public UserRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
        UserRealm authRealm = new UserRealm();
        authRealm.setCredentialsMatcher(matcher);
        return authRealm;
    }

    //配置自定义的密码比较器
    @Bean
    public CredentialsMatcher credentialsMatcher() {
        return (token, info) -> {
            UsernamePasswordToken utoken = (UsernamePasswordToken) token;
            //获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
            String inPassword = new String(utoken.getPassword());
            //获得数据库中的密码
            String dbPassword = (String) info.getCredentials();
            //进行密码的比对
            return inPassword.equals(dbPassword);
        };
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }
}